//    Copyright (C) Kherty.  All rights reserved.
#region

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Text;

#endregion

namespace OpenLS.Spreadsheet.Expressions
{
    [Obsolete]
    internal class RangeListReference : RangeReference
    {
        private readonly List<RangeReference> References;
        private readonly char separator = ','; //\\

        public RangeListReference(List<RangeReference> refs)
        {
            
            References = refs;
        }
#if DEBUG
        [ContractInvariantMethod]
        private void ObjectInvariant()
        {
            Contract.Invariant(References != null);
        }
#endif


        private RangeListReference(IEnumerable<RangeReference> refs)
        {
            Contract.Requires(Enumerable.All(refs, r => r != null));
            References = new List<RangeReference>(refs);
        }
        public static RangeListReference Combine (RangeReference r1, RangeReference r2)
        {
            return new RangeListReference  ( Enumerable.Concat (GetReferencesOf(r1), GetReferencesOf(r2)));
            
        }

        static IEnumerable<RangeReference> GetReferencesOf (RangeReference rangeReference)
        {
            if (rangeReference is RangeListReference)
            {
                RangeListReference rlr = (RangeListReference) rangeReference;
                foreach (var reference in rlr.References)
                {
                    yield return reference;
                }
            }
            else
            {
                yield return rangeReference;
            }
        }
        public override Worksheet Worksheet
        {
            get { return References[0].Worksheet; }
        }

        public override string FullLabel
        {
            get
            {
                return "(" + StringEnumerable.Concat(References, rr => rr.FullLabel, separator) + ")";
                var b = new StringBuilder();
                b.Append('(');
                var last = References[References.Count - 1];
                foreach (var r in References)
                {
                    b.Append(r.FullLabel);
                    if (r != last)
                        b.Append(separator);
                }
                b.Append(')');
                return b.ToString();
            }
        }

        protected override Range GetRange()
        {
            return new CompositeRange(new List<SimpleRange>(
                                          Enumerable.Where(Enumerable.Select(References, rr => (SimpleRange) rr.Range), rr => rr != null)));
        }


        public override string Label
        {
            get
            {
                return "(" + StringEnumerable.Concat(References, rr => rr.Label, separator);
                var b = new StringBuilder();
                var last = References[References.Count - 1];
                b.Append('(');
                foreach (var rr in References)
                {
                    b.Append(rr.Label);
                    if (rr != last)
                        b.Append(separator);
                }
                b.Append(')');
                return b.ToString();
            }
        }

        public override RangeReference Offset(CellRelativeAddress address)
        {
            return new RangeListReference(Enumerable.Select(this.References, rr => rr.Offset(address)));
        }

        internal override RangeReference Transposed(Cell target)
        {
            throw new NotImplementedException();
        }

        internal override RangeReference Projected(Worksheet targetWorksheet)
        {
            throw new NotImplementedException();
        }

        public static RangeListReference Create(RangeReference reference, CellReference cellReference)
        {
            return Create(reference, new SingleCellRangeReference(cellReference));
        }
        public static RangeListReference Create(RangeReference first, RangeReference second)
        {
            List<RangeReference> items = new List<RangeReference>();
            items.AddRange(getFlatReferences(first));
            items.AddRange(getFlatReferences(second));
            return new RangeListReference(items);
        }

        static IEnumerable<RangeReference> getFlatReferences (RangeReference rr)
        {
            if (rr is RangeListReference)
            {
                RangeListReference rlr = (RangeListReference) rr;
                foreach (var item in Enumerable.SelectMany(rlr.References, i => getFlatReferences(i)))
                {
                    yield return item;
                }
            }
            else
            {
                yield return rr;
            }
        }
    }
}